package org.jfunny.core.meta;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.jfunny.core.dfa.DFA;
import org.jfunny.core.dfa.State;
import org.jfunny.core.ds.Arg;
import org.jfunny.core.ds.Loop;
import org.jfunny.core.ds.Statement;
import org.jfunny.core.parser.Parser;
import org.jfunny.core.util.StringUtil;

public class Mapping {
	private String key;
	private String value;
	private String keyName;

	private Statement keyStatement;
	private Statement valueStatement;
	private State starter;
	
	private boolean isSysMapping;
	private boolean isRegexMapping;
	
	public Mapping(String keyName, String key, String value, boolean isSysMapping) {
		this.key = key;
		this.value = value;
		this.keyName = keyName;
		this.isSysMapping = isSysMapping;

		List<Statement> keyTemplate = new LinkedList<Statement>();
		keyTemplate.addAll(getTemplate(key));
		keyStatement = new Arg();
		((Arg)keyStatement).setChildren(keyTemplate);

		List<Statement> valueTemplate = new LinkedList<Statement>();
		valueTemplate.addAll(getTemplate(value));
		valueStatement = new Arg();
		((Arg)valueStatement).setChildren(valueTemplate);

		starter = DFA.getInstance().toDFA(keyTemplate);
	}
	
	protected List<Statement> getTemplate(String statement) {
		if (key.contains(Loop.PAREN_L)) {
			return getRegex("{" + statement + "}");
		}
		else {
			return Parser.parse("{" + statement + "}").getChildren();
		}
	}
	
	public String getKey() {
		return key;
	}

	public String getValue() {
		return value;
	}

	public String getKeyName() {
		return keyName;
	}

	public String getValueName() {
		String funcName = StringUtil.substringAfter(value, "(");
		funcName = funcName.trim();
		funcName = StringUtil.substringBefore(funcName, " ");
		return funcName;
	}

	public Statement getKeyStatement() {
		return keyStatement;
	}

	public Statement getValueStatement() {
		return valueStatement;
	}

	public State getStarter() {
		return starter;
	}
	
	public boolean isSysMapping() {
		return isSysMapping;
	}

	public boolean isRegexMapping() {
		return isRegexMapping;
	}

	private static List<Statement> getRegex(String template) {
		List<Statement> list = new LinkedList<Statement>();

		String before;
		String between;
		String after = template;
		while (after.contains(Loop.PAREN_L)) {
			before = StringUtil.substringBefore(after, Loop.PAREN_L).trim() + "}";
			if (!"{}".equals(before)) {
				//list.add(ParserJfunny.parse(before));
				list.addAll(Parser.parse(before).getChildren());
			}
			between = StringUtil.substringBetween(after, Loop.PAREN_L, Loop.PAREN_R).trim();
			after = StringUtil.substringAfter(after, Loop.PAREN_R).trim();

			if (after.startsWith("?")) {
				after = "{" + StringUtil.substringAfter(after, "?");
				Loop pattern = new Loop(Loop.ZERO_ONE);
				between = "{" + between + "}";
				pattern.setChildren((ArrayList<Statement>) Parser.parse(between).getChildren());
				list.add(pattern);
			}
			else if (after.startsWith("*")) {
				after = "{" + StringUtil.substringAfter(after, "*");
				Loop pattern = new Loop(Loop.ZERO_MORE);
				between = "{" + between + "}";
				pattern.setChildren((ArrayList<Statement>) Parser.parse(between).getChildren());
				list.add(pattern);
			}
			else if (after.startsWith("+")) {
				after = "{" + StringUtil.substringAfter(after, "+");
				Loop pattern = new Loop(Loop.ONE_MORE);
				between = "{" + between + "}";
				pattern.setChildren((ArrayList<Statement>) Parser.parse(between).getChildren());
				list.add(pattern);
			}
			else {
				System.out.println("Error!");
			}

		}
		if (!"{}".equals(after)) {
			//list.add(ParserJfunny.parse(after));
			list.addAll(Parser.parse(after).getChildren());
		}

		return list;
	}
}
